package com.zxq.tcp.handler.dispatch;


import com.zxq.exchange.enums.EFrame;
import com.zxq.exchange.model.ExchangeDTO;
import com.zxq.exchange.register.INotifyDevice;
import com.zxq.exchange.register.NotifyDeviceRegister;
import com.zxq.exchange.register.NotifyPlatformRegister;
import com.zxq.factory.FastFrame;
import com.zxq.tcp.cache.TcpChannelCache;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteBuffer;

@Slf4j
public abstract class TCPDispatchHandler<T> implements ITcpDispatchHandler, INotifyDevice {

    public TCPDispatchHandler next = null;

    public TCPDispatchHandler() {
        NotifyDeviceRegister.getInstance(getTcpFrame()).registerNotify(this);
    }

    protected ByteBuf in;
    protected ChannelHandlerContext channel;
    public void injectByteBuf(ChannelHandlerContext channel,ByteBuf in) {
        this.in = in;
        this.channel = channel;
    }

    public final void handlerFrame() {

        if(isThisFrame()) {
            decodeFrame();
        } else if(next != null) {
            next.handlerFrame();
        } else {
            log.info("not find this com.zxq.common.handler");
        }

    }

    @Override
    public void decodeFrame() {
        ExchangeDTO exchangeDTO = decodeExchangeDTO();
        // 心跳包和注册包为null，不和平台交互
        if(exchangeDTO != null) {
            exchangeDTO.setFrame(getTcpFrame());
            exchangeDTO.setDevId(TcpChannelCache.getDevId(channel));
            NotifyPlatformRegister.getInstance(getTcpFrame()).notifyMessage(exchangeDTO);
        }
    }


    protected abstract ExchangeDTO decodeExchangeDTO();


    @Override
    public void notifyDevice(ExchangeDTO exchangeDTO) {
           if(exchangeDTO.getFrame() == getTcpFrame()) {
               ChannelHandlerContext channelHandlerContext = TcpChannelCache.getChannel(exchangeDTO.getDevId());
               T object = produceFrame(exchangeDTO.getCmdHex(),exchangeDTO.getData());
               if(object != null) {
                   byte[] frame = FastFrame.encoder(object);
                   channelHandlerContext.write(ByteBuffer.wrap(frame));
               }
           }
    }

    /**
     * 生成对应的帧数据
     * @param cmd_id 指令id
     * @param data 数据协议
     * @return
     */
    protected abstract T produceFrame(String cmd_id, byte[] data);

    /**
     * 获取帧id
     * @return
     */
    protected abstract EFrame getTcpFrame();



}
